package hn.sigit.logic.viewer.toolbox;

import hn.sigit.dao.hnd.administrative.HND_NaturalPersonDAO;
import hn.sigit.dao.hnd.cadastre.HND_ParcelDAO;
import hn.sigit.dao.hnd.cadastre.HND_SpatialZoneDAO;
import hn.sigit.dao.ladm.administrative.LA_RightDAO;
import hn.sigit.dao.ladm.party.LA_PartyDAO;
import hn.sigit.logic.viewer.InteractiveViewerHelper;
import hn.sigit.model.commons.IParcel;
import hn.sigit.model.commons.ISpatialZone;
import hn.sigit.model.hnd.administrative.HND_NaturalPerson;
import hn.sigit.model.hnd.cadastre.HND_Parcel;
import hn.sigit.model.hnd.administrative.HND_Property;
import hn.sigit.model.hnd.cadastre.HND_SpatialZone;
import hn.sigit.model.ladm.administrative.LA_BAUnit;
import hn.sigit.model.ladm.administrative.LA_Right;
import hn.sigit.model.ladm.party.LA_Party;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

public class SearchHelper {
	private static final String BY_CADASTRALKEY = "0";
	private static final String BY_MUNICIPALKEY = "1";
	private static final String BY_FIELDTAB = "2";
	private static final String BY_NAME = "3";
	private static final String BY_OWNERID = "4";
	
	
	private InteractiveViewerHelper interactiveViewerHelper;
	private String searchCriteria;
	private String searchText;
	
	private Double envelopeLeft = 0.0;
	private Double envelopeBottom = 0.0;
	private Double envelopeRight = 0.0;
	private Double envelopeTop = 0.0;
	
	private List<? extends ISpatialZone> searchResultList;

	
	public SearchHelper(InteractiveViewerHelper ivh) {
		interactiveViewerHelper = ivh;
		searchCriteria = BY_CADASTRALKEY;
	}

	
	public String getSearchCriteria() {
		return searchCriteria;
	}
	public void setSearchCriteria(String searchCriteria) {
		this.searchCriteria = searchCriteria;
	}

	public String getSearchText() {
		return searchText;
	}
	public void setSearchText(String searchText) {
		this.searchText = searchText;
	}
	
	public List<? extends ISpatialZone> getSearchResultList() {
		if (searchResultList == null) {
			searchResultList = new ArrayList<HND_SpatialZone>();
		}
		return searchResultList;
	}
	public void setSearchResultList(List<? extends ISpatialZone> searchResultList) {
		this.searchResultList = searchResultList;
	}


	public String doSearch() {
		if (searchText == null) return null;
		
		searchText = searchText.trim();
		setSearchResultList(null);
		
		List<HND_SpatialZone> szList = null;
		List<HND_Parcel> parcelList = null;
		
		if (searchCriteria.equals(BY_CADASTRALKEY)) {
			parcelList = HND_ParcelDAO.loadParcelsByCadastralKey(searchText);
		}
		else if (searchCriteria.equals(BY_MUNICIPALKEY)) {
			parcelList = HND_ParcelDAO.loadParcelsByMunicipalKey(searchText);
		}
		else if (searchCriteria.equals(BY_FIELDTAB)) {
			try {
				Long fieldTab = Long.parseLong(searchText);
				parcelList = HND_ParcelDAO.loadParcelsByFieldTab(fieldTab);
			}
			catch (NumberFormatException e) {
				FacesContext.getCurrentInstance().addMessage(
						"",
						new FacesMessage(
								FacesMessage.SEVERITY_ERROR,
								"Numero de ficha de campo invalido",
								""
						)
				);
				
				return null;
			}
		}
		else if (searchCriteria.equals(BY_NAME)) {
			szList = HND_SpatialZoneDAO.loadSpatialZonesByNameAndLayer(searchText,
					interactiveViewerHelper.getSelectedLayer());
		}
		else if (searchCriteria.equals(BY_OWNERID)) {
			searchText = searchText.replace("-", ""); 
			HND_NaturalPerson person = HND_NaturalPersonDAO.loadNatPersonPartyByIdentity(searchText);
			LA_Party party = LA_PartyDAO.loadPartyByExtParty(person);
			List<LA_Right> rightList = LA_RightDAO.loadRightsByParty(party);
			
			parcelList = new ArrayList<HND_Parcel>();
			for (LA_Right right : rightList) {
				LA_BAUnit baUnit = right.getBaunit();
				if (baUnit instanceof HND_Property) {
					Set<IParcel> parcelSet = ((HND_Property) baUnit).getParcels();
					for (IParcel parcel : parcelSet) {
						if (parcel instanceof HND_Parcel)
						parcelList.add((HND_Parcel) parcel);
					}
				}
			}
		}
		
		double[] envelopeCoords = null;
		
		searchResultList = (szList != null ? szList
				: (parcelList != null ? parcelList
						: new ArrayList<HND_SpatialZone>()));

		if (searchResultList.size() > 0) {
			envelopeCoords = interactiveViewerHelper.getGeneralHelperInstance().calcSZsZoomEnvelope(searchResultList);
			
			if (envelopeCoords != null && envelopeCoords.length > 3) {
				envelopeLeft = envelopeCoords[0];
				envelopeBottom = envelopeCoords[1];
				envelopeRight = envelopeCoords[2];
				envelopeTop = envelopeCoords[3];
			}
		}
		else {
			FacesContext.getCurrentInstance().addMessage(
					"",
					new FacesMessage(
							FacesMessage.SEVERITY_ERROR,
							interactiveViewerHelper.getResBundle().loadMessage("txt.no_search_results"),
							""
					)
			);
		}
		
		return null;
	}
	
	
	public String doSelection() {
		if (getSearchResultList().size() > 0) {
			List<HND_SpatialZone> szList = interactiveViewerHelper.getHighlightedSpatialZoneList();
			for (ISpatialZone sz : getSearchResultList()) {
				if (!szList.contains(sz))
					szList.add((HND_SpatialZone) sz);
			}
		}
		else {
			FacesContext.getCurrentInstance().addMessage(
					"",
					new FacesMessage(
							FacesMessage.SEVERITY_ERROR,
							"No hay seleccion",
							//interactiveViewerHelper.getResBundle().loadMessage("txt.no_search_results"),
							""
					)
			);
		}

		return null;
	}


	public String getBY_OWNERID() {
		return BY_OWNERID;
	}
	public String getBY_FIELDTAB() {
		return BY_FIELDTAB;
	}
	public String getBY_MUNICIPALKEY() {
		return BY_MUNICIPALKEY;
	}
	public String getBY_NAME() {
		return BY_NAME;
	}
	public String getBY_CADASTRALKEY() {
		return BY_CADASTRALKEY;
	}


	public Double getEnvelopeLeft() {
		return envelopeLeft;
	}
	public Double getEnvelopeBottom() {
		return envelopeBottom;
	}
	public Double getEnvelopeRight() {
		return envelopeRight;
	}
	public Double getEnvelopeTop() {
		return envelopeTop;
	}
}
